(function (vue, name) {
  vue.component(name, {
    template: '<div>\
        <slot name="dialog"></slot>\
        <div :id="toolbarID"></div>\
        <div :id="outlineID" style="background:url(\'libs/mxgraph/images/grid.gif\');position: absolute;z-index:2;background-color:#fff;width:300px;height:150px; overflow: hidden;" v-if="workType==\'serviceModule\'"></div>\
        <div :id="containerID" style="position:relative;background:url(\'libs/mxgraph/images/grid.gif\');" :style="{height:height+\'px\'}"></div>\
      </div>',
    props: {
      height: { //画布高度
        type: Number,
        default: 500
      },
      isNewWorkflow: { //是否初始化，初始化需要自动生成根节点或者开始结束节点
        type: Boolean,
        default: true
      },
      workType: { // 可选值workflow:流程图, serviceModule：服务模块部署
        type: String,
        default: 'workflow'
      },
      status: { // 默认编辑状态，可以增加删除子元素，show,展示状态，不能新增删除子元素，可以启动或暂停
        type: String,
        default: 'edit'
      },
      viewType: { // 预览类型， view时不可编辑,默认会将lock状态设置为true
        type: String,
        default: ''
      },
      lock:{ // 是否锁定graph
        type: Boolean,
        default: false
      }
    },
    data: function () {
      return {
        locked: this.viewType === 'view' || this.lock,
        graph: null,
        editor: null,
        outline: null,
        toolbar: null,
        layoutAnimate: true,
        size: null,
        edges: [],
        defaultStyle: {
          [mxConstants.STYLE_SHAPE]: mxConstants.SHAPE_LABEL,
          [mxConstants.STYLE_PERIMETER]: mxPerimeter.RectanglePerimeter,
          [mxConstants.STYLE_ROUNDED]: true,
          [mxConstants.STYLE_ARCSIZE]: 10, // 设置圆角程度

          [mxConstants.STYLE_STROKECOLOR]: '#fffff',
          [mxConstants.STYLE_FONTCOLOR]: '#000000',
          [mxConstants.STYLE_FILLCOLOR]: '#FFFFFF',
          [mxConstants.STYLE_FONTSIZE]: 20,

          [mxConstants.STYLE_ALIGN]: mxConstants.ALIGN_CENTER,
          [mxConstants.STYLE_EDGE]: mxConstants.EDGESTYLE_ORTHOGONAL,
          [mxConstants.STYLE_IMAGE_ALIGN]: mxConstants.ALIGN_CENTER,
          [mxConstants.STYLE_ROTATABLE]: 0,
          // [mxConstants.STYLE_IMAGE_VERTICAL_ALIGN]: mxConstants.ALIGN_TOP,

          [mxConstants.STYLE_IMAGE_WIDTH]: '72',
          [mxConstants.STYLE_IMAGE_HEIGHT]: '72'
        },
        containerID: ''
      };
    },
    created: function () {
      window.mxBasePath = 'libs/mxgraph/';
      this.containerID = 'graph_' + new Date().getTime();
      this.toolbarID = 'toolbar_' + new Date().getTime();
      this.outlineID = 'outline_' + new Date().getTime();
    },
    mounted: function () {
      try {
        if (!mxClient.isBrowserSupported()) {
          mxUtils.error('Browser is not supported!', 200, false);
        } else {
          this.initEditor()
        }
      } catch (e) {
        console.log('初始化mxGraph报错!', e)
      }
    },
    destroyed: function() {
      this.graph.getTooltipForCell = null;
      this.graph.destroy();
      this.graph = null;
    },
    methods: {
      addStyle: function(obj) {
        for(var k in obj) {
          var vertexStyle = mxUtils.clone(this.defaultStyle);
          // 如果workType不为workflow，隐藏工具栏,并且自动初始化根节点
          vertexStyle[mxConstants.STYLE_FILLCOLOR] = obj[k];
          this.graph.getStylesheet().putCellStyle('custom-style-' + k, vertexStyle);
        }
      },
      _setDefaultSettings: function () {
        mxGraph.prototype.htmlLabels = true;
        mxGraph.prototype.isWrapping = function (cell) {
          return true;
        };
        mxConstants.DEFAULT_HOTSPOT = 1;
        // Enables guides
        mxGraphHandler.prototype.guidesEnabled = true;
        // Alt disables guides
        mxGuide.prototype.isEnabledForEvent = function (evt) {
          return !mxEvent.isAltDown(evt);
        };
        // Enables snapping waypoints to terminals
        mxEdgeHandler.prototype.snapToTerminals = true;
      },
      _resetGraphSettings:function(){
        // #TODO 根据当前图类型及状态，配置对应的默认信息
        this.graph.setCellsResizable(false); //禁止改变节点大小
        this.graph.foldingEnabled = false; //节点不可展开
        this.graph.setCellsEditable(false); //节点不可编辑
        this.graph.setTooltips(false); //鼠标移入节点不展示节点信息
        this.graph.setDropEnabled(true); //从工具栏拖动到目标细胞时细胞边界是否产生光圈
        mxGraphHandler.prototype.guidesEnabled = true; //显示细胞位置标尺
        this.graph.center(true,true,0.5,0.5); // 将画布放到容器中间
        var sc = this.graph.getView().getScale(); // 获取当前的缩放比例
        this.graph.zoomTo(Math.round(sc/2)); // 在缩放一半，否则是满屏状态，不好看
      },
      _loadXML: function (xml) {
        return mxUtils.load(xml)
      },
      /**
       * @description 获取graph编辑器
       * @param {String} xml xml文件路径
       */
      _getGraphEditor: function (xml) {
        var node = this._loadXML(xml).getDocumentElement();
        var graphElement = node.getElementsByTagName('add')[0];
        graphElement.setAttribute('element', this.containerID);
        return new mxEditor(node);
      },
      /**
       * @description 初始化基础对象
       */
      initEditor: function () {
        var _this = this;
        this._setDefaultSettings();
        var container = document.getElementById(this.containerID);
        mxEvent.disableContextMenu(container); //禁用右键
        this.editor = this._getGraphEditor(mxBasePath + '/config-server/workfloweditor.xml');
        if (this.workType !== "workflow") {
          this.graph = new mxGraph(container);
          this.graph.setConnectable(false);
        } else {
          this.graph = this.editor.graph;
        }
        this.graph.cellsEditable = false; // 禁用编辑(连线的value)
        this.size = this.getContainerSize();
        this._resetGraphSettings();
        // 节点双击事件
        this.graph.addListener(mxEvent.DOUBLE_CLICK, function (sender, evt) {
          var cell = evt.getProperty('cell');
          if (!cell || cell.data.nodetype === "start" || cell.data.nodetype === "end" || cell.data.nodetype == "button" || cell.data.nodetype == "line") {
            return;
          };
          _this.$emit('celldblclick', cell);
        });
        // 节点单击事件
        this.graph.addListener(mxEvent.CLICK, function (sender, evt) {
          var cell = evt.getProperty('cell');
          _this.clearCellOverLay();
          if(cell && cell.vertex && _this.viewType === 'view'){
            // 预览视图，并且节点
            _this.graph.addCellOverlay(cell, _this.createOverlay(new mxImage(mxBasePath + '/images/overlays/run.png', 20, 20), '启动', mxConstants.ALIGN_RIGHT, mxConstants.ALIGN_BOTTOM, new mxPoint(-24, 0), {type:'start'}));
            _this.graph.addCellOverlay(cell, _this.createOverlay(new mxImage(mxBasePath + '/images/overlays/stop.png', 20, 20), '停止', mxConstants.ALIGN_RIGHT, mxConstants.ALIGN_BOTTOM, null, {type:'stop'}));
          }
        });
        // 禁用右键菜单
        this.graph.popupMenuHandler.factoryMethod = null;
        this.locked && this.lockGraph();
        // 显示缩略图
        this.outline = new mxOutline(this.graph, document.getElementById(this.outlineID));
        this.outline.labelsVisible = true;
        // 定义折线样式
        var style = this.graph.getStylesheet().getDefaultEdgeStyle();
        Object.assign(style, {
          [mxConstants.STYLE_ROUNDED]: true, // 设置线条拐弯处为圆角
          [mxConstants.STYLE_STROKEWIDTH]: '1',
          [mxConstants.STYLE_STROKECOLOR]: '#333333',
          [mxConstants.STYLE_EDGE]: mxConstants.EDGESTYLE_ORTHOGONAL, // 设置折线
          [mxConstants.STYLE_FONTCOLOR]: '#33333',
          [mxConstants.STYLE_LABEL_BACKGROUNDCOLOR]: '#ffa94d'
        });
        this.graph.connectionHandler.createEdgeState = function () {
          var edge = this.createEdge();
          return new mxCellState(_this.graph.view, edge, _this.graph.getCellStyle(edge));
        };
      },
      lockGraph: function(){
        this.graph.setEnabled(false);
      },
      load: function (xml) {
        var doc = mxUtils.parseXml(xml);
        var codec = new mxCodec(doc);
        codec.decode(doc.documentElement, this.graph.getModel());
        // 遍历所有节点并增加overlay
        var cells = this.graph.getModel().cells
        for(var k in cells){
          if(cells[k].vertex){
            this.addCellOverlay(cells[k]);
          }
        }
        this._resetGraphSettings();
      },
      /**
       * @description 加载json对象数据
       * @param {Array<Object>} data 数据集
       */
      loadData:function(data, options){
        if(data && data.length > 0) {
          var nodeList = [], edgeList = [], width = this.size.width;
          var typeList = options.classification;
          for(var i = 0, l = data.length, d; i < l; i++) {
            d = yufp.clone(data[i], {});
            d['nodetype'] = d.serverType;
            nodeList.push({
              id: d.serverId,
              value: d.serverName,
              x: 0,
              y: 0,
              width: 160,
              height: 80,
              style: 'custom-style-' + d.serverType,
              relative: false,
              nodetype: d.serverType,
              data: d
            })
            if (d.parentId && d.parentId !== '0') {
              edgeList.push({
                id: d.parentId + '-' + d.serverId,
                // value: 'edge-' + i,
                value: '',
                source: d.parentId,
                target: d.serverId
              });
            }
          }
          nodeList.length > 0 && this.addVertexList(null, nodeList);
          edgeList.length > 0 && this.addEdgeList(null, edgeList);
        }
        this.layout();
      },
      /**
       * @description 自动布局
       */
      layout: function () {
        var layout = new mxHierarchicalLayout(this.graph);
        layout.orientation = mxConstants.DIRECTION_NORTH;
        layout.resizeParent = true;
        layout.moveParent = true;
        layout.execute(this.graph.getDefaultParent());
        // this.organicLayout();
        this.graph.fit(); // 自适应
        this.graph.center(true, true, 0.5, 0.5); // 将画布放到容器中间
        var sc = this.graph.getView().getScale(); // 获取当前的缩放比例
        sc = sc > 1 ? 1 : 0.8
        this.graph.zoomTo(sc); // 在缩放一半，否则是满屏状态，不好看
      },
      /**
       * @description 添加节点
       * @param {Object} parent 父节点
       * @param {String} id 节点ID
       * @param {String} value 节点显示值
       * @param {Number} x 节点x轴位置
       * @param {Number} y 节点y轴位置
       * @param {Number} width 节点宽度
       * @param {Number} height 节点高度
       * @param {String} style 节点样式字符串
       * @param {Boolean} relative 是否相对位置，默认false
       * @param {Object} data 节点数据属性
       */
      addVertex: function (parent, id, value, x, y, width, height, style, relative, data) {
        var cellName = this.getCellName(value);
        parent = parent || this.graph.getDefaultParent();
        this.graph.getModel().beginUpdate();
		 var v1 ;
        try {
         v1 = this.graph.insertVertex(
            parent,
            id,
            cellName,
            x || 100,
            y || 200,
            width || 160,
            height || 80,
            'custom-style-' + data.serverType,
            relative
          );
          data = data || {};
          data.nodetype = data.serverType || value;
          v1.data = data;
          this.addCellOverlay(v1);
        } catch(e) {
         
        }
		this.layout();
		this.graph.getModel().endUpdate();
		return v1;
      },
      /**
       * @description 批量增加节点
       * @param {Object} parent 父节点
       * @param {Array<Object>} list 节点列表 
       */
      addVertexList: function(parent, list){
        var _this = this;
        parent = parent || this.graph.getDefaultParent();
        this.graph.getModel().beginUpdate();
        var nodeList = [];
        try {
          for(var i = 0, l = list.length, node, tmpData, cell; i < l; i++) {
            node = list[i];
            var cellName = _this.getCellName(node.value);
            cell = this.graph.insertVertex(
              parent,
              node.id,
              cellName,
              node.x,
              node.y,
              node.width,
              node.height,
              node.style,
              node.relative
            )
            nodeList.push(cell);
            tmpData = node.data || {};
            tmpData.nodetype = node.nodetype || node.value;
            nodeList[nodeList.length - 1].data = tmpData;
            this.addCellOverlay(cell);
          }
        } catch(e) {
         
        }
		this.graph.getModel().endUpdate();
		return nodeList;
      },
      /**
       * 修改节点信息
       */
      updateVertex: function (currentVertex, modulename, data) {
        var cellName = this.getCellName(modulename);
        currentVertex.setValue(cellName);
        currentVertex.data = data;
        this.graph.refresh(currentVertex);
      },
      // 节点名字超长时 做换行处理
      getCellName(label) {
        return '<div style="width: 160px; height: 80px; display: table-cell; vertical-align: middle; font-size: 12px; word-break: break-all;">' + label + '</div>';
      },
      // 清除节点运行图标
      clearCellOverLay:function(){
        var _this = this;
        var cells = this.graph.getModel().cells;
        var cell = null;
        for(var k in cells){
          cell = cells[k];
          if(cell && cell.overlays){
            var overlays = cell.overlays;
            for(var i = overlays.length - 1; i >= 0; i--){
              if(overlays[i].data && (overlays[i].data.type == 'start' || overlays[i].data.type == 'stop')){
                _this.graph.removeCellOverlay(cell, overlays[i]);
              }
            }
          }
        }
      },
      /**
       * @description 增加节点图标
       * @param {Object} cell 节点
       */
      addCellOverlay: function(cell) {
        var _this = this;
        if(this.viewType !== 'view') {
          if(cell && cell.data && cell.data.nodetype !== 'S'){
            var overlay = new mxCellOverlay(
              new mxImage(mxBasePath + '/images/overlays/delete.png', 16, 16), '删除节点', mxConstants.ALIGN_RIGHT, mxConstants.ALIGN_TOP, null, 'pointer');
            overlay.addListener(mxEvent.CLICK, function(sender, evt) {
              _this.$emit('delclick', evt.properties.cell);
            });
            this.graph.addCellOverlay(cell, overlay);
          }
          if(cell && cell.data && cell.data.nodetype !== 'N'  && cell.data.nodetype !== 'C' ) {
            var overlay = new mxCellOverlay(
              new mxImage(mxBasePath + '/images/overlays/add.png', 16, 16), '新增节点', mxConstants.ALIGN_CENTER, mxConstants.ALIGN_BOTTOM, null, 'pointer');
            overlay.addListener(mxEvent.CLICK, function(sender, evt) {
              _this.$emit('addbtnclick', evt.properties.cell);
            });
            this.graph.addCellOverlay(cell, overlay);
          }
        }
      },
      /**
       * @description 增加连线
       * @param {Object} parent 容器节点
       * @param {Object} edge 连线对象 
       */
      addEdge: function(parent, edgeObj) {
        parent = parent || this.graph.getDefaultParent();
        this.graph.getModel().beginUpdate();
        var edge;
        try {
          edge = this.graph.insertEdge(
            parent,
            edgeObj.id,
            edgeObj.value || '',
            this.getVertex(edgeObj.source),
            this.getVertex(edgeObj.target),
            edgeObj.style || ''
          );
        } catch(e) {
          console.log('添加连线异常', edge);
        } finally {
          this.layout();
          this.graph.getModel().endUpdate();
        }
      },
      /**
       * @description 批量增加连线
       * @param {Object} parent 容器节点
       * @param {Array<Object>} list 连线列表 
       */
      addEdgeList: function(parent, list){
        parent = parent || this.graph.getDefaultParent();
        this.graph.getModel().beginUpdate();
        var edgeList = [];
        try {
          for(var i = 0, l = list.length, edge, tmpData; i < l; i++) {
            edge = list[i];
            edgeList.push(this.graph.insertEdge(
              parent,
              edge.id,
              edge.value || '',
              this.getVertex(edge.source),
              this.getVertex(edge.target),
              edge.style || ''
            ));
            tmpData = edge.data || {};
            tmpData.nodetype = edge.nodetype || edge.value;
            edgeList[edgeList.length - 1].data = tmpData;
          }
        } catch(e) {
          console.log('添加连线异常', e);
        } 
		this.graph.getModel().endUpdate();
		return edgeList;
      },
      createOverlay: function (image, tooltip, align, verticalAlign, point, data) {
        var _this = this;
        var overlay = new mxCellOverlay(image, tooltip, align || mxConstants.ALIGN_RIGHT, verticalAlign || mxConstants.ALIGN_BOTTOM, point || new mxPoint(0, 0), 'pointer');
        overlay.addListener(mxEvent.CLICK, function(sender, evt) {
          console.log('overlay click', arguments);
          _this.$emit('overlayclick', sender, evt.properties.cell);
        });
        overlay.data = data || {};
        return overlay;
      },
      getVertex: function (id) {
        return this.graph.getModel().getCell(id);
      },
      /**
       * @description 环形布局
       */
      circleLayout: function(){
        var _this = this;
        this.graph.getModel().beginUpdate();
        var parent = this.graph.getDefaultParent();
        try {
          // Creates a layout algorithm to be used
          // with the graph
          var circleLayout = new mxCircleLayout(this.graph);
          circleLayout.execute(parent);
        } catch (e) {
          throw e;
        } finally {
          if (this.layoutAnimate) {
            var morph = new mxMorphing(this.graph);
            morph.addListener(mxEvent.DONE, function()
            {
              _this.graph.getModel().endUpdate();
            });
            
            morph.startAnimation();
          } else {
            _this.graph.getModel().endUpdate();
          }
        }
      },
      organicLayout:function(){
        var _this = this;
        this.graph.getModel().beginUpdate();
        var parent = this.graph.getDefaultParent();
				try {
          var layout = new mxHierarchicalLayout(this.graph);
          layout.orientation = mxConstants.DIRECTION_NORTH;
          layout.execute(parent);
        } catch (e) {
          throw e;
        } finally {
          if (this.layoutAnimate) {
            var morph = new mxMorphing(this.graph, 10, 1.7, 20);
            morph.addListener(mxEvent.DONE, function() {
              _this.graph.getModel().endUpdate();
            });
            morph.startAnimation();
          } else {
            _this.graph.getModel().endUpdate();
          }
        }
      },
      compactTreeLayout:function(){
        var _this = this;
        this.graph.getModel().beginUpdate();
        var parent = this.graph.getDefaultParent();
				try {
          var layout = new mxCompactTreeLayout(this.graph);
          layout.horizontal = false;
          layout.execute(parent);
        } catch (e) {
          throw e;
        } finally {
          if (this.layoutAnimate) {
            // Default values are 6, 1.5, 20
            var morph = new mxMorphing(this.graph, 10, 1.7, 20);
            morph.addListener(mxEvent.DONE, function() {
              _this.graph.getModel().endUpdate();
            });
            morph.startAnimation();
          } else {
            _this.graph.getModel().endUpdate();
          }
        }
      },
      circleLayoutCustom: function(graph, cell){
        var cx = graph.container.clientWidth / 2;
        var cy = graph.container.clientHeight / 2;
        var parent = graph.getDefaultParent();
        graph.getModel().beginUpdate();
        try {
          // for (var key in graph.getModel().cells) {
          //   var tmp = graph.getModel().getCell(key);
          //   var model = this.graph.getModel();
          //   if (tmp != cell && graph.getModel().isVertex(tmp)) {
          //     graph.removeCells([tmp]);
          //   }
          // }

          // // Merges the response model with the client model
          // graph.getModel().mergeChildren(model.getRoot().getChildAt(0), parent);

          // // Moves the given cell to the center
          // var geo = graph.getModel().getGeometry(cell);

          // if (geo != null) {
          //   geo = geo.clone();
          //   geo.x = cx - geo.width / 2;
          //   geo.y = cy - geo.height / 2;

          //   graph.getModel().setGeometry(cell, geo);
          // }

          // Creates a list of the new vertices, if there is more
          // than the center vertex which might have existed
          // previously, then this needs to be changed to analyze
          // the target model before calling mergeChildren above
          var vertices = [];
          var model = this.graph.getModel();
          
          for (var key in graph.getModel().cells) {
            var tmp = graph.getModel().getCell(key);
            
            if (tmp != cell && model.isVertex(tmp)) {
              vertices.push(tmp);

              // Changes the initial location "in-place"
              // to get a nice animation effect from the
              // center to the radius of the circle
              var geo = model.getGeometry(tmp);

              if (geo != null) {
                geo.x = cx - geo.width / 2;
                geo.y = cy - geo.height / 2;
              }
            }
          }
          
          // Arranges the response in a circle
          var cellCount = vertices.length;
          var phi = 2 * Math.PI / cellCount;
          var r = Math.min(graph.container.clientWidth / 4, graph.container.clientHeight / 4);
          console.log('为支点信息', vertices);
          for (var i = 0; i < cellCount; i++) {
            var geo = graph.getModel().getGeometry(vertices[i]);
            
            if (geo != null) {
              geo = geo.clone();
              geo.x += r * Math.sin(i * phi);
              geo.y += r * Math.cos(i * phi);

              graph.getModel().setGeometry(vertices[i], geo);
            }
          }
        }
        finally {
          // Updates the display
          graph.getModel().endUpdate();
        }
      },
      graphZoom:function(t){
        var s = this.graph.getView().getScale();
        this.graph.zoomTo(t > 0 ? (s += 0.1) : (s -= 0.1));
      },
      /**
       * @description 获取指定节点下所有节点
       * @param {Object} cell 指定的节点
       * @param {Boolean} edge 是否包含连线, 默认false
       */
      getChildCells: function(cell, edge){
        var childCells = {};
        if(cell) {
          var cells = this.graph.getModel().cells;
          for(var k in cells) {
            var item = cells[k];
            if (item.vertex && item.id === cell.id) {
              childCells[item.id] = item;
            }
            // 连线目标存储
            if (item.edge && item.target.id === cell.id) {
              if (edge) {
                childCells[item.id] = item;
              }
            }
            // 计算当前节点连接出去的线
            if (item.edge && item.source.id === cell.id) {
              if (edge) {
                childCells[item.id] = item;
              }
              var tmpCell = this.getChildCells(item.target, edge);
              if(tmpCell) {
                childCells = yufp.extend(tmpCell, childCells)
              }
            }
          }
          return childCells;
        }
        return null;
      },
      /**
       * @description 删除节点
       * @param {Object} vertex 节点
       */
      delVertex: function (vertex) {
        this.graph.removeCells(vertex, true);
        // var _this = this;
        // vertex.removeFromParent();
        // _this._delEdge(vertex);
        // var parent = this.graph.getDefaultParent();
        // var parentChildren = parent.children;
        // for (var i = 0; i < parentChildren.length; i++) {
        //   var child = parentChildren[i];
        //   if (!child.isVisible()) {
        //     continue;
        //   };
        //   if (child.data.parentId == vertex.getId()) {
        //     child.removeFromParent();
        //     _this.delEdge(child);
        //     _this.graph.refresh(child); // 删除节点或者线必须调用，不然画布还是删除之前的状态
        //     _this.delVertex(child);
        //   };
        // };
        // _this.graph.refresh(vertex);
      },
      /**
       * @description 删除连线，不需要调用，删除节点时已经自动调用
       * @param {Object} vertex 节点
       */
      _delEdge: function (vertex) {
        var edges = this._getEdges();
        for (var i = 0; i < edges.length; i++) {
          if (edges[i].source.id === vertex.getId() || edges[i].target.id === vertex.getId()) {
            edges[i].removeFromParent();
            this.graph.refresh(edges[i]);
            this.outline.refresh();
          }
        }
      },
      _getEdges: function() {
        var edgeList = [];
        this.graph.getModel().cells.forEach(function(item) {
          item.edge && edgeList.push(item);
        });
        return edgeList;
      },
      /**
       * @description 导出图形XML字符串
       */
      exportXML: function () {
        var encoder = new mxCodec();
        var node = encoder.encode(this.graph.getModel());
        return mxUtils.getXml(node);
      },
      updateWorkStates:function(states){
        var model = this.graph.getModel();
        model.beginUpdate();
        try {
          for (var i = 0; i < states.length; i++) {
            var id = states[i].serverId;
            var state = states[i].state;
            var cell = model.getCell(id);
            
            if (cell != null)
            {
              this.graph.removeCellOverlays(cell);
              if (state == 'OFF') {
                this.graph.addCellOverlay(cell, this.createOverlay(new mxImage(mxBasePath + '/images/overlays/status_stop.png', 20, 20), state, mxConstants.ALIGN_LEFT, mxConstants.ALIGN_TOP));
              } else if (state == 'ON') {
                this.graph.addCellOverlay(cell, this.createOverlay(new mxImage(mxBasePath + '/images/overlays/status_success.png', 20, 20), state, mxConstants.ALIGN_LEFT, mxConstants.ALIGN_TOP));
              } else if (state == 'stoping') {
                this.graph.addCellOverlay(cell, this.createOverlay(new mxImage(mxBasePath + '/images/overlays/status_exception.png', 20, 20), state, mxConstants.ALIGN_LEFT, mxConstants.ALIGN_TOP));
              }
            }
          } // for
        } finally {
          model.endUpdate();
        }
      },
      /**
       * @description 读取本地xml文件
       * @param {Event} evt 文件读取事件
       */
      readLocalXMLFile: function (evt) {
        const _this = this;
        let file = evt.target.files[0];
        let reader = new FileReader();
        reader.onload = e => {
          let xml = e.target.result;
          var doc = mxUtils.parseXml(xml);
          var dec = new mxCodec(doc);
          dec.decode(doc.documentElement, _this.graph.getModel());
          _this.graph.getModel().endUpdate();
        };
        reader.readAsText(file);
      },
      /**
       * @description 获取容器尺寸
       */
      getContainerSize: function () {
        var containter = this.graph.container
        return {
          width: containter.clientWidth,
          height: containter.clientHeight
        }
      }
    }
  });
}(Vue, 'yu-workflow-server'));